package cn.edu.sjtu.se.dslab.rhapsody.parse;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import cn.edu.sjtu.se.dslab.project.BusZone;
import cn.edu.sjtu.se.dslab.project.DisplayZone;
import cn.edu.sjtu.se.dslab.project.EntityZone;
import cn.edu.sjtu.se.dslab.rhapsody.entity.BusAgent;
import cn.edu.sjtu.se.dslab.rhapsody.entity.DisplayView;
import cn.edu.sjtu.se.dslab.rhapsody.entity.Event;
import cn.edu.sjtu.se.dslab.util.FileUtil;

/**
 * 将xmi解析的结果序列化到文件中，方便下次显示
 * @author thinker
 *
 */
public class XmiSerializer {
	private static final Logger logger = Logger.getLogger(XmiSerializer.class);
	
	private static final String ENTITY_ZONE_FILE = "serializer/entityZone.txt";
	private static final String DISPLAY_ZONE_FILE = "serializer/displayZone.txt";
	private static final String BUS_AGENT_FILE = "serializer/busAgent.txt";
	private static final String DISPLAY_VIEW_FILE = "serializer/displayView.txt";
	private static final String CONTROL_RESPONSE_FILE = "serializer/controlResponse.txt";
	private static final String BUS_ZONE_FILE = "serializer/busZone.txt";
	
	/**
	 * 从文件中反序列化显示数据区
	 * @param projectFolderPath
	 * @return
	 */
	final public List<DisplayZone> readDisplayZones(String projectFolderPath){
		File file = new File(FileUtil.getRootPath() + projectFolderPath + DISPLAY_ZONE_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectInputStream ois = null;
		List<DisplayZone> displayZones = new ArrayList<DisplayZone>();
		try{
			ois = new ObjectInputStream(new FileInputStream(file));
			while(true){
				Object obj = ois.readObject();
				if (null == obj) break;
				displayZones.add((DisplayZone)obj);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getMessage());
		} catch (ClassNotFoundException e) {
			logger.error(e.getStackTrace());
		}finally{
			if (null != ois){
				try {
					ois.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
		return displayZones;
	}
	
	/**
	 * 从文件中反序列化实体数据区
	 * @param projectFolderPath
	 * @return
	 */
	final public List<EntityZone> readEntityZones(String projectFolderPath){
		File file = new File(FileUtil.getRootPath() + projectFolderPath + ENTITY_ZONE_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectInputStream ois = null;
		List<EntityZone> entityZones = new ArrayList<EntityZone>();
		try{
			ois = new ObjectInputStream(new FileInputStream(file));
			while(true){
				Object obj = ois.readObject();
				if (null == obj) break;
				entityZones.add((EntityZone)obj);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		} catch (ClassNotFoundException e) {
			logger.error(e.getStackTrace());
		}finally{
			if (null != ois){
				try {
					ois.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
		return entityZones;
	}
	
	/**
	 * 从文件中反序列化总线数据区
	 * @param projectFolderPath
	 * @return
	 */
	public List<BusZone> readBusZones(String projectFolderPath) {
		File file = new File(FileUtil.getRootPath() + projectFolderPath + BUS_ZONE_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectInputStream ois = null;
		List<BusZone> busZones = new ArrayList<BusZone>();
		try{
			ois = new ObjectInputStream(new FileInputStream(file));
			while(true){
				Object obj = ois.readObject();
				if (null == obj) break;
				busZones.add((BusZone)obj);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		} catch (ClassNotFoundException e) {
			logger.error(e.getStackTrace());
		}finally{
			if (null != ois){
				try {
					ois.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
		return busZones;
	}
	
	/**
	 * 从文件中反序列化总线通信代理
	 * @param projectFolderPath
	 * @return
	 */
	final public List<BusAgent> readBusAgent(String projectFolderPath){
		List<BusAgent> busAgents = new ArrayList<BusAgent>();  //先创建保证在文件不存在的时候仍然能够返回空的列表
		File file = new File(FileUtil.getRootPath() + projectFolderPath + BUS_AGENT_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectInputStream ois = null;
		try{
			ois = new ObjectInputStream(new FileInputStream(file));
			while(true){
				Object obj = ois.readObject();
				if (null == obj) break;
				busAgents.add((BusAgent)obj);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		} catch (ClassNotFoundException e) {
			logger.error(e.getStackTrace());
		}finally{
			if (null != ois){
				try {
					ois.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
		return busAgents;
	}
	
	/**
	 * 从文件中反序列化显示页面
	 * @param projectFolderPath
	 * @return
	 */
	final public List<DisplayView> readDisplayAgent(String projectFolderPath){
		File file = new File(FileUtil.getRootPath() + projectFolderPath + DISPLAY_VIEW_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectInputStream ois = null;
		List<DisplayView> displayAgents = new ArrayList<DisplayView>();
		try{
			ois = new ObjectInputStream(new FileInputStream(file));
			while(true){
				Object obj = ois.readObject();
				if (null == obj) break;
				displayAgents.add((DisplayView)obj);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		} catch (ClassNotFoundException e) {
			logger.error(e.getStackTrace());
		}finally{
			if (null != ois){
				try {
					ois.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
		return displayAgents;
	}
	
	/**
	 * 从文件中反序列化控制响应
	 * @param projectFolderPath
	 * @return
	 */
	final public List<Event> readControlResponse(String projectFolderPath){
		File file = new File(FileUtil.getRootPath() + projectFolderPath + CONTROL_RESPONSE_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectInputStream ois = null;
		List<Event> events = new ArrayList<Event>();
		try{
			ois = new ObjectInputStream(new FileInputStream(file));
			while(true){
				Object obj = ois.readObject();
				if (null == obj) break;
				events.add((Event)obj);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		} catch (ClassNotFoundException e) {
			logger.error(e.getStackTrace());
		}finally{
			if (null != ois){
				try {
					ois.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
		return events;
	}
	
	/**
	 * 序列化显示数据区到文件中
	 * @param doc
	 * @param projectFolderPath
	 */
	final public void writeDisplayZones(XmiDocument doc,  String projectFolderPath){
		File file = new File(FileUtil.getRootPath() + projectFolderPath + DISPLAY_ZONE_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectOutputStream oos = null;
		try{
			if (!file.exists()){
				FileUtil.createDirectorys(projectFolderPath + "serializer/");
				file.createNewFile();
			}
			oos = new ObjectOutputStream(new FileOutputStream(file));
			for (DisplayZone displayZone: doc.getDisplayZones()){
				oos.writeObject(displayZone);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		}finally{
			if (null != oos){
				try {
					oos.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
	}
	
	/**
	 * 序列化实体数据区到文件中
	 * @param doc
	 * @param projectFolderPath
	 */
	final public void writeEntityZones(XmiDocument doc,  String projectFolderPath){
		File file = new File(FileUtil.getRootPath() + projectFolderPath + ENTITY_ZONE_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectOutputStream oos = null;
		try{
			if (!file.exists()){
				FileUtil.createDirectorys(projectFolderPath + "serializer/");
				file.createNewFile();
			}
			oos = new ObjectOutputStream(new FileOutputStream(file));
			for (EntityZone entityZone: doc.getEntityZones()){
				oos.writeObject(entityZone);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		}finally{
			if (null != oos){
				try {
					oos.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
	}
	
	/**
	 * 序列化总线数据区到文件中
	 * @param doc
	 * @param projectFolderPath
	 */
	final public void writeBusZones(XmiDocument doc,  String projectFolderPath){
		File file = new File(FileUtil.getRootPath() + projectFolderPath + BUS_ZONE_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectOutputStream oos = null;
		try{
			if (!file.exists()){
				FileUtil.createDirectorys(projectFolderPath + "serializer/");
				file.createNewFile();
			}
			oos = new ObjectOutputStream(new FileOutputStream(file));
			for (BusZone busZone: doc.getBusZones()){
				oos.writeObject(busZone);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		}finally{
			if (null != oos){
				try {
					oos.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
	}
	
	/**
	 * 序列化总线通信代理到文件中
	 * @param doc
	 * @param projectFolderPath
	 */
	final public void writeBusAgents(XmiDocument doc,  String projectFolderPath){
		File file = new File(FileUtil.getRootPath() + projectFolderPath + BUS_AGENT_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectOutputStream oos = null;
		try{
			if (!file.exists()){
				FileUtil.createDirectorys(projectFolderPath + "serializer/");
				file.createNewFile();
			}
			oos = new ObjectOutputStream(new FileOutputStream(file));
			for (BusAgent busAgent: doc.getBusAgents()){
				oos.writeObject(busAgent);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		}finally{
			if (null != oos){
				try {
					oos.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
	}
	
	/**
	 * 序列化显示页面到文件中
	 * @param doc
	 * @param projectFolderPath
	 */
	final public void writeDisplayViews(XmiDocument doc,  String projectFolderPath){
		File file = new File(FileUtil.getRootPath() + projectFolderPath + DISPLAY_VIEW_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectOutputStream oos = null;
		try{
			if (!file.exists()){
				FileUtil.createDirectorys(projectFolderPath + "serializer/");
				file.createNewFile();
			}
			oos = new ObjectOutputStream(new FileOutputStream(file));
			for (DisplayView displayAgent: doc.getDisplayAgents()){
				oos.writeObject(displayAgent);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		}finally{
			if (null != oos){
				try {
					oos.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
	}
	
	/**
	 * 序列化控制响应事件
	 * @param doc
	 * @param projectFolderPath
	 */
	final public void writeControlResponse(XmiDocument doc,  String projectFolderPath){
		File file = new File(FileUtil.getRootPath() + projectFolderPath + CONTROL_RESPONSE_FILE);
		logger.info("Read File:" + file.getAbsolutePath());
		ObjectOutputStream oos = null;
		try{
			if (!file.exists()){
				FileUtil.createDirectorys(projectFolderPath + "serializer/");
				file.createNewFile();
			}
			oos = new ObjectOutputStream(new FileOutputStream(file));
			for ( Event event : doc.getControlResponses()){
				oos.writeObject(event);
			}
		}catch(FileNotFoundException fe){
			logger.error(fe.getStackTrace());
		}catch(IOException ioe){
			logger.error(ioe.getStackTrace());
		}finally{
			if (null != oos){
				try {
					oos.close();
				} catch (IOException e) {
					logger.error(e.getStackTrace());
				}
			}
		}
	}


}
